/*
******************************************************************************************************* 
**  Copyright (C) 2019, 苏州检易生物科技有限公司 
**  All rights reserved. 
** 
**  FileName:       	can.c
**  Description:		fpga middle transmit protocol	FPGA与中位机电机协议
**  Author:        	 
**  Version				v0.1
**  Date:           	2019-11-26
**	Function List： 
**  History:         
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	调试开关
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "can_mem.h"
#include "log_console.h"
#include "os_config.h"



/*
*********************************************************************************************************
*                                              	宏定义
*********************************************************************************************************
*/

#define		CAN_MEM_BLOCKS				(192)
/*
*********************************************************************************************************
*                                              	结构体定义
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	函数原型声明
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	全局变量定义
*********************************************************************************************************
*/
static struct rt_mempool 	rt_can_mp;
static uint8_t __attribute__((aligned(4))) rt_can_mp_buff[RT_MEMPOOL_BYTE_SIZE(CAN_MEM_BLOCKS,sizeof(can_mem_node_t))];

/*
*********************************************************************************************************
*                                              	模块静态变量定义
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                              	函数定义
*********************************************************************************************************
*/

can_mem_err_t	can_mem_init(void)
{	
	if(RT_EOK != rt_mp_init(&rt_can_mp,
		"can msg pool",
		rt_can_mp_buff,
		sizeof(rt_can_mp_buff),
		sizeof(can_mem_node_t)
		))
	{
		Critical_Log("can mem create failed!\r\n");
		return CAN_MEM_ERR_INIT;
	}
	return CAN_MEM_ERR_NONE;
}

/*TBD can mem 不够怎么办*/
can_mem_node_t* can_mem_malloc(void)
{
	can_mem_node_t * p_can_msg = rt_mp_alloc(&rt_can_mp,RT_WAITING_NO);
	if(NULL==p_can_msg)
	{
		Critical_Log("Can mem create failed!\r\n");
		return NULL;
	}
	if(rt_can_mp.block_free_count < 8)
		Trace_Log("Warning can mp reach full,remain %d!\r\n",rt_can_mp.block_free_count);
	memset(p_can_msg,0,sizeof(can_mem_node_t));
	return p_can_msg;
}

can_mem_err_t can_mem_free(can_mem_node_t* p_node)
{
	rt_mp_free(p_node);
	return CAN_MEM_ERR_NONE;
}

can_mem_err_t can_mem_list_free(can_mem_list_t* p_list,can_mem_node_t* p_node)
{
	if(NULL == p_list || NULL == p_node || p_list->cur_size == 0 || p_list->p_head == NULL)
		return CAN_MEM_ERR_FORMAT;
	rt_base_t it = rt_hw_interrupt_disable();

	can_mem_node_t* p_next = p_list->p_head;
	if(p_next == p_node)
	{
		p_list->cur_size--;
		p_list->p_head = p_list->p_head->next;
		can_mem_free(p_node);
	}
	else
	{
		while(p_next->next != NULL && p_next->next != p_node)
		{
			p_next = p_next->next;
		}
		if(p_next->next == p_node)
		{
			p_list->cur_size--;
			p_next->next = p_node->next;
			can_mem_free(p_node);
		}
		else
		{
			rt_hw_interrupt_enable(it);
			return CAN_MEM_ERR_PUT;
		}
	}
	rt_hw_interrupt_enable(it);
	return CAN_MEM_ERR_NONE;
}
can_mem_node_t* can_mem_list_malloc(can_mem_list_t* p_list)
{
	if(p_list == NULL || p_list->cur_size >= p_list->max_size)
		return NULL;
	can_mem_node_t* p_new = can_mem_malloc();
	memset(p_new,0,sizeof(can_mem_node_t));
	if(p_new == NULL)
		return NULL;
	can_mem_list_push(p_list,p_new);
//	can_mem_node_t* p_tail = p_list->p_head;
//	if(p_tail == NULL)
//	{
//		p_list->p_head = p_new;
//	}
//	else
//	{
//		while(p_tail->next != NULL)
//		{p_tail = p_tail->next;}
//		p_tail->next = p_new;
//	}
//	p_list->cur_size++;
	return p_new;
}
can_mem_node_t* can_mem_list_pop(can_mem_list_t* p_list)
{
	if(p_list == NULL || p_list->p_head == NULL)
		return NULL;
	rt_base_t it = rt_hw_interrupt_disable();

	can_mem_node_t* p_rtn = p_list->p_head;
	p_list->p_head = p_list->p_head->next;
	p_list->cur_size--;
	rt_hw_interrupt_enable(it);
	return p_rtn;
}

can_mem_err_t can_mem_list_push(can_mem_list_t* p_list,can_mem_node_t* p_node)
{
	ASSERT(p_list != NULL && p_node != NULL && p_list->cur_size < p_list->max_size);
//	if(p_list == NULL || p_node == NULL || p_list->cur_size >= p_list->max_size)
//		return CAN_MEM_ERR_FORMAT;
	rt_base_t it = rt_hw_interrupt_disable();

	p_node->next = NULL;
	can_mem_node_t* p_tail = p_list->p_head;
	if(p_tail == NULL)
	{
		p_list->p_head = p_node;
	}
	else
	{
		while(p_tail->next != NULL)
		{p_tail = p_tail->next;}
		p_tail->next = p_node;
	}
	p_list->cur_size++;
	rt_hw_interrupt_enable(it);
	return CAN_MEM_ERR_NONE;
}
